package com.coolwar.地图.地理围栏;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.file.FileReader;
import cn.hutool.json.JSONUtil;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;

public class Test {


    /**
     * 黄冈市黄州区 地理围栏
     *
     * 1. 获取行政区划的地理围栏数据可以利用百度API。<a href="https://api.map.baidu.com/lbsapi/getpoint/index.html">百度拾取坐标系统</a>
     * var bdary = new BMap.Boundary();
     * bdary.get("北京市延庆区", function(res){ //获取行政区域
     * //这里是用户自己的函数。
     * var count = res.boundaries.length;
     * console.info("length of bounds ="+count)
     * console.info(res.boundaries[0])
     * });
     */
    private static final String geofencing = "114.848173, 30.450719;114.850185, 30.449058;114.857906, 30.443893;114.86253, 30.441456;114.867659, 30.43907;114.871187, 30.436084;114.874861, 30.433065;114.879137, 30.429714;114.881376, 30.428124;114.885453, 30.425233;114.888639, 30.423309;114.890302, 30.422443;114.894259, 30.4214;114.898356, 30.420432;114.905607, 30.418651;114.910905, 30.417748;114.920908, 30.416248;114.931958, 30.414852;114.934667, 30.414446;114.942854, 30.413851;114.952547, 30.412843;114.959937, 30.411939;114.963383, 30.411833;114.967292, 30.411699;114.971083, 30.4115;114.976595, 30.411238;114.979494, 30.411131;114.983357, 30.411135;114.988705, 30.411202;114.992221, 30.411009;114.996953, 30.410994;115.001885, 30.411375;115.005013, 30.411488;115.012209, 30.411603;115.015731, 30.41144;115.017832, 30.413847;115.016669, 30.430954;115.015701, 30.43301;115.014254, 30.442319;115.012575, 30.450168;115.012116, 30.454408;115.009592, 30.462462;115.009999, 30.473216;115.013807, 30.488964;115.018053, 30.499839;115.02213, 30.507511;115.025544, 30.520445;115.027918, 30.530349;115.032708, 30.54257;115.037536, 30.546158;115.040958, 30.548194;115.044252, 30.548949;115.051528, 30.547724;115.060377, 30.545886;115.065687, 30.544121;115.068924, 30.544743;115.072728, 30.547616;115.073376, 30.551618;115.073176, 30.553631;115.072876, 30.556673;115.072125, 30.559245;115.070596, 30.565995;115.070149, 30.573948;115.070561, 30.579377;115.071107, 30.581963;115.071308, 30.585876;115.071314, 30.591983;115.071796, 30.595251;115.073607, 30.598709;115.07589, 30.601936;115.077301, 30.603778;115.079045, 30.606377;115.082559, 30.610939;115.079662, 30.613157;115.075275, 30.618587;115.074904, 30.619499;115.074859, 30.620124;115.074923, 30.620605;115.075966, 30.623155;115.073649, 30.626706;115.073453, 30.628099;115.073475, 30.629348;115.07338, 30.630261;115.073011, 30.631269;115.068209, 30.638365;115.065041, 30.642834;115.063745, 30.644601;115.061037, 30.644478;115.05675, 30.649046;115.054262, 30.648875;115.053278, 30.646175;115.052324, 30.6453;115.050231, 30.645615;115.048943, 30.644642;115.049118, 30.641905;115.046882, 30.640394;115.048067, 30.638578;115.04372, 30.633354;115.043715, 30.629846;115.039869, 30.628239;115.039076, 30.627179;115.040541, 30.62555;115.040732, 30.623868;115.039457, 30.619129;115.037627, 30.617368;115.037567, 30.615565;115.037255, 30.613641;115.035692, 30.612966;115.026152, 30.612653;115.025243, 30.612292;115.024858, 30.611606;115.026084, 30.608929;115.026702, 30.602167;115.026569, 30.60065;115.025113, 30.599467;115.021573, 30.59762;115.021086, 30.597143;115.020644, 30.596275;115.020644, 30.594805;115.020491, 30.593703;115.020055, 30.593089;115.019063, 30.592642;115.017761, 30.592754;115.008474, 30.596034;115.007438, 30.59624;115.005677, 30.59612;115.004819, 30.595841;115.002913, 30.593703;115.00205, 30.593219;115.001624, 30.593252;115.000962, 30.593545;115.000567, 30.593785;115.000035, 30.593913;114.99816, 30.590559;114.999567, 30.588685;115.000322, 30.587677;115.000359, 30.586734;114.999999, 30.585985;114.999323, 30.585496;114.998199, 30.58534;114.993373, 30.585463;114.992651, 30.585321;114.992318, 30.58464;114.992363, 30.580421;114.992325, 30.579779;114.991809, 30.579263;114.99095, 30.578963;114.990441, 30.57886;114.989348, 30.578864;114.988651, 30.578651;114.987934, 30.577335;114.987084, 30.575976;114.985818, 30.575247;114.983111, 30.574341;114.982772, 30.57397;114.982814, 30.5702;114.981887, 30.568979;114.980652, 30.568453;114.979526, 30.568014;114.978299, 30.567853;114.977021, 30.567829;114.975748, 30.568127;114.968173, 30.572771;114.967323, 30.572824;114.966314, 30.572787;114.965463, 30.572655;114.964497, 30.572017;114.963737, 30.570964;114.963294, 30.569909;114.964789, 30.564203;114.963342, 30.563384;114.95823, 30.561971;114.954144, 30.561367;114.947961, 30.563263;114.947304, 30.563511;114.946671, 30.563552;114.945901, 30.563385;114.944467, 30.562889;114.94126, 30.562239;114.940388, 30.562252;114.939887, 30.562316;114.939125, 30.562516;114.938312, 30.562897;114.927476, 30.568694;114.926188, 30.569889;114.926177, 30.570785;114.929424, 30.575249;114.929453, 30.575409;114.929432, 30.575685;114.929173, 30.576004;114.926654, 30.577016;114.926205, 30.577759;114.924609, 30.583217;114.923753, 30.58705;114.923855, 30.589694;114.925849, 30.592893;114.923497, 30.597335;114.922393, 30.597472;114.919345, 30.597169;114.9176, 30.601173;114.914873, 30.599699;114.91268, 30.601447;114.909673, 30.599434;114.908247, 30.599764;114.905005, 30.60535;114.902451, 30.610893;114.900819, 30.611694;114.8986, 30.611104;114.88711, 30.60683;114.882298, 30.60614;114.874641, 30.605402;114.874768, 30.600755;114.873994, 30.599259;114.866564, 30.595532;114.861161, 30.594408;114.854661, 30.594155;114.853328, 30.59399;114.849983, 30.592132;114.847657, 30.588952;114.847842, 30.581411;114.845775, 30.577085;114.842564, 30.573629;114.843163, 30.570356;114.843911, 30.566898;114.844777, 30.559661;114.843969, 30.548858;114.844232, 30.538075;114.843206, 30.524973;114.841159, 30.512342;114.840738, 30.510302;114.840118, 30.502288;114.840931, 30.492785;114.840992, 30.483297;114.840979, 30.474794;114.84151, 30.471133;114.842412, 30.468337;114.84459, 30.459308;114.844972, 30.457299;114.848173, 30.450719";
//    private static final String geofencing = "0,0;1000,0;1000,1000;0,500;0,0";

    /**
     * 格子边长
     */
    private static final int gridLength = 500;
//    private static final double gridLength = 50;

    public static void main(String[] args) throws IOException {
        // 1.拿到地理围栏4个顶点经纬度
        // 2.根据格子边长确认中心点经纬度 & 4个顶点经纬度
        // 3.去除不在地理围栏得格子
        // 4.根据数据经纬度计算所在的格子 并累加数据

        List<Grid> grids = getGrids();
        FileReader fileReader = new FileReader("C:\\Users\\ADMIN\\Desktop\\00.txt");
        String s = fileReader.readString();
        List<Map> list = JSONUtil.toList(s, Map.class);

        for (Map map : list) {
            String date = (String) map.get("date");
            String base_id = (String) map.get("base_id");
            String cell_id = (String) map.get("cell_id");
            String lng = (String) map.get("lng");
            String lat = (String) map.get("lat");
            String count = (String) map.get("count");
            Point point = new Point(parseInt(lat), parseInt(lng));
            for (Grid grid : grids) {
                List<Point> areaPoints = new ArrayList<>();
                areaPoints.add(grid.getLl());
                areaPoints.add(grid.getRl());
                areaPoints.add(grid.getRu());
                areaPoints.add(grid.getLu());
                areaPoints.add(grid.getLl());
                if (GeoUtils.checkIsInPolygon(point, areaPoints)) {
                    grid.setDate(date);
                    grid.setBase_id(base_id);
                    grid.setCell_id(cell_id);
                    if (grid.getCount() > 0) {
                        grid.setCount(grid.getCount() + Integer.parseInt(count));
                    } else {
                        grid.setCount(Integer.parseInt(count));
                    }
                    break;
                }
            }
        }
        List<GridDate> ll = new ArrayList<>();
        for (Grid grid : grids) {
            grid.setLng(String.valueOf(grid.getCenter().getLng()).substring(0, 3) + "." + String.valueOf(grid.getCenter().getLng()).substring(3, 9));
            grid.setLat(String.valueOf(grid.getCenter().getLat()).substring(0, 2) + "." + String.valueOf(grid.getCenter().getLat()).substring(2, 8));
            ll.add(BeanUtil.copyProperties(grid, GridDate.class));
        }
        System.out.println(ll.size());
        FileWriter fw = new FileWriter("C:\\Users\\ADMIN\\Desktop\\new.txt");
        BufferedWriter out = new BufferedWriter(fw);
        out.write(JSONUtil.toJsonStr(ll));
        out.close();
    }

    /**
     * @return 地理围栏4个顶点经纬度 & 围栏区域经纬度列表
     */
    private static Map<String, Object> getVertex(String geofencing) {
        List<Integer> lats = new ArrayList<>();
        List<Integer> lngs = new ArrayList<>();
        String[] split = geofencing.split(";");

        List<Point> areaAroundPoints = new ArrayList<>();
        for (String s : split) {
            String[] split1 = s.split(",");
            int lng = parseInt(split1[0]);
            int lat = parseInt(split1[1]);
            lats.add(lat);
            lngs.add(lng);

            areaAroundPoints.add(new Point(lat, lng));
        }

        Optional<Integer> latMax = lats.stream().sorted().max(Integer::compareTo);
        Optional<Integer> latMin = lats.stream().sorted().min(Integer::compareTo);

        Optional<Integer> lngMax = lngs.stream().sorted().max(Integer::compareTo);
        Optional<Integer> lngMin = lngs.stream().sorted().min(Integer::compareTo);

        Map<String, Object> map = new HashMap<>();
        map.put("lngMax", lngMax.get());
        map.put("latMin", latMin.get());
        map.put("latMax", latMax.get());
        map.put("lngMin", lngMin.get());
        map.put("areaAroundPoints", areaAroundPoints);

        System.out.println("       地理围栏顶点经纬度      ");
        System.out.println("----------" + map.get("latMax") + "----------");
        System.out.println("-                           -");
        System.out.println("-                           -");
        System.out.println(map.get("lngMin") + "                  " + map.get("lngMax"));
        System.out.println("-                           -");
        System.out.println("-                           -");
        System.out.println("----------" + map.get("latMin") + "----------");
        System.out.println("格子边长：" + gridLength);
        System.out.println("经度距离:" + (lngMax.get() - lngMin.get()));
        System.out.println("维度距离:" + (latMax.get() - latMin.get()));
        System.out.println("预计格子数量:" + ((lngMax.get() - lngMin.get()) / gridLength * (latMax.get() - latMin.get()) / gridLength));
        return map;
    }

    /**
     * 获取地理围栏内的所有格子
     */
    private static List<Grid> getGrids() {
        int existCount = 0;
        int notExistCount = 0;

        Map<String, Object> vertex = getVertex(geofencing);
        int latMin = (int) vertex.get("latMin");
        int latMax = (int) vertex.get("latMax");
        int lngMin = (int) vertex.get("lngMin");
        int lngMax = (int) vertex.get("lngMax");
        List<Point> areaAroundPoints = (List<Point>) vertex.get("areaAroundPoints");
        List<Grid> list = new ArrayList<>();

        int lngStart = lngMin - gridLength;
        int latStart = latMin;
        while (lngStart < lngMax) {
            lngStart += gridLength;
            Grid grid = new Grid();
            grid.setCenter(new Point(latStart + gridLength / 2, lngStart + gridLength / 2));
            grid.setLl(new Point(latStart, lngStart));
            grid.setRl(new Point(latStart, lngStart + gridLength));
            grid.setRu(new Point(latStart + gridLength, lngStart + gridLength));
            grid.setLu(new Point(latStart + gridLength, lngStart));
            list.add(grid);
            existCount++;
        }
        List<Grid> z = BeanUtil.copyToList(list, Grid.class);
        while (latStart < latMax) {
            List<Grid> y = new ArrayList<>();
            latStart += gridLength;
            for (Grid grid : z) {
                Grid uGrid = new Grid();
                uGrid.setCenter(new Point(grid.getCenter().getLat() + gridLength, grid.getCenter().getLng()));
                uGrid.setLl(new Point(grid.getLu().getLat(), grid.getLu().getLng()));
                uGrid.setRl(new Point(grid.getRu().getLat(), grid.getRu().getLng()));
                uGrid.setLu(new Point(uGrid.getLl().getLat() + gridLength, uGrid.getLl().getLng()));
                uGrid.setRu(new Point(uGrid.getRl().getLat() + gridLength, uGrid.getRl().getLng()));
                list.add(uGrid);
                y.add(uGrid);
                existCount++;
            }
            z = y;
        }
        System.out.println("计算格子数：" + existCount);
        Iterator<Grid> iterator = list.iterator();
        while (iterator.hasNext()) {
            Grid next = iterator.next();
            // 不在围栏内
            if (!GeoUtils.checkIsInPolygon(next.getCenter(), areaAroundPoints)) {
                notExistCount++;
                iterator.remove();
            }
        }
        System.out.println("不在围栏格子数：" + notExistCount);
        System.out.println("剩余格子数：" + list.size());
        return list;
    }

    private static Integer parseInt(String str) {
        StringBuilder replace1 = new StringBuilder(str.replace(".", "").replace(" ", ""));
        int length1 = replace1.length();
        if (replace1.toString().startsWith("114") || replace1.toString().startsWith("115")) {
            for (int i = 0; i < (9 - length1); i++) {
                replace1.append("0");
            }
        } else {
            for (int i = 0; i < (8 - length1); i++) {
                replace1.append("0");
            }
        }
        return Integer.parseInt(replace1.toString());
    }
}
